package net.asrsmid.config;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * public class AsRsConfig<br><br>
 * An AsRsConfig is a bean which contains all settings loaded from the XML config file
 * @author Chen WANG
 * @since 29 May 2011
 */
public class AsRsConfig {
	private class AsApplicationMap {
		private Map<String, AsApplication> map;
		public AsApplicationMap() {
			map = new HashMap<String, AsApplication>();
		}
		public AsApplication get(String appId) {
			if (map.get(appId) == null)
				map.put(appId, new AsApplication(appId));
			
			return map.get(appId);
		}
		public void put(String appId, AsApplication asApp) {
			map.put(appId, asApp);
		}
		public Map<String, AsApplication> getMap() {
			return map;
		}
	}
	private class RsApplicationMap {
		private Map<String, RsApplication> map;
		public RsApplicationMap() {
			map = new HashMap<String, RsApplication>();
		}
		public RsApplication get(String appId) {
			if (map.get(appId) == null)
				map.put(appId, new RsApplication(appId));
			
			return map.get(appId);
		}
		public void put(String appId, RsApplication rsApp) {
			map.put(appId, rsApp);
		}
		public Map<String, RsApplication> getMap() {
			return map;
		}
	}
	private class RsReportMap {
		private Map<String, RsReport> map;
		public RsReportMap() {
			map = new HashMap<String, RsReport>();
		}

		public void put(RsReport report) {
			map.put(report.getAppId() + ":" + report.getName(), report);
		}
		public RsReport get(String appId, String name) {
			return map.get(appId + ":" + name);
		}
	}
	
	private AsApplicationMap asApplications;
	private RsApplicationMap rsApplications;
	private RsReportMap rsReports;
	
	/**
	 * Constructs an AsRsConfig object without parameters
	 */
	public AsRsConfig() {
		asApplications = new AsApplicationMap();
		rsApplications = new RsApplicationMap();
		rsReports = new RsReportMap();
	}
	
	/**
	 * Constructs an AsRsConfig with the given asAppId list and the rsAppId list 
	 * @param asAppIdList a list of as-application id
	 * @param rsAppIdList a list of rs-application id
	 */
	public AsRsConfig(List<String> asAppIdList, List<String> rsAppIdList) {
		asApplications = new AsApplicationMap();
		rsApplications = new RsApplicationMap();
		
		for(String asAppId : asAppIdList) {
			asApplications.put(asAppId, new AsApplication(asAppId));
		}
		
		for(String rsAppId : rsAppIdList) {
			rsApplications.put(rsAppId, new RsApplication(rsAppId));
		}
	}
	
	/**
	 * Returns an AsApplication object with the given application id
	 * @param appId AsApplication application id
	 * @return an AsApplication object
	 */
	public AsApplication getAsApplication(String appId) {
		return asApplications.get(appId);
	}
	
	/**
	 * Returns a RsApplication object with the given application id
	 * @param appId RsApplication application id
	 * @return a RsApplication object
	 */
	public RsApplication getRsApplication(String appId) {
		return rsApplications.get(appId);
	}
	
	/**
	 * Saves an AsApplication object
	 * @param asApp the AsApplication object to save
	 */
	public void putAsApplication(AsApplication asApp) {
		asApplications.put(asApp.getAppId(), asApp);
	}
	
	/**
	 * Saves an RsApplication object
	 * @param rsApp the RsApplication object to save
	 */
	public void putRsApplication(RsApplication rsApp) {
		rsApplications.put(rsApp.getAppId(), rsApp);
	}
	
	/**
	 * Returns a collection of all the saved AsApplication objects
	 * @return a collection of AsApplication
	 */
	public Collection<AsApplication> getAsApplications() {
		return asApplications.getMap().values();
	}
	
	/**
	 * Returns a collection of all the saved RsApplication objects
	 * @return a collection of RsApplication
	 */
	public Collection<RsApplication> getRsApplications() {
		return rsApplications.getMap().values();
	}
	
	/**
	 * Returns an olap4j connection string based on the arguments loaded from the config file. 
	 * <br>An olap4j connection has a common form like : <br>
	 * <code>jdbc:xmla:Server=http://server/olap/msmdpump.dll;Catalog=AdventureWorksDW2008R2;
	 * Cube=Adventure Works</code><br>
	 * @param appId as-application id
	 * @return An olap4j connection string
	 */
	public String getAsOlapConnectionString(String appId) {
		return asApplications.get(appId).getOlapConnectionString();
	}

	/**
	 * Returns the authentication mode used for Analysis Services 
	 * @param appId as-application id
	 * @return the asAuthMode
	 */
	public AsRsAuthMode getAsAuthMode(String appId) {
		return asApplications.get(appId).getAuthMode();
	}

	/**
	 * Sets the authentication mode used for Analysis Services
	 * @param appId as-application id
	 * @param asAuthMode the asAuthMode to set
	 */
	public void setAsAuthMode(String appId, AsRsAuthMode asAuthMode) {
		asApplications.get(appId).setAuthMode(asAuthMode);
	}

	/**
	 * Returns the default username for Analysis Services <br>
	 * The default username will be used only in
	 * <code>BASIC</code> or <code>CUSTOMIZED</code>
	 * authentication mode and only when an username is not 
	 * provided by user (Eg. user input in GUI) 
	 * @param appId as-application id
	 * @return the asDefaultUserName
	 */
	public String getAsDefaultUserName(String appId) {
		return asApplications.get(appId).getDefaultUserName();
	}

	/**
	 * Sets the default username for Analysis Services <br>
	 * The default username will be used only in
	 * <code>BASIC</code> or <code>CUSTOMIZED</code>
	 * authentication mode and only when an username is not 
	 * provided by user (Eg. user input in GUI) 
	 * @param appId as-application id
	 * @param asDefaultUserName the asDefaultUserName to set
	 */
	public void setAsDefaultUserName(String appId, String asDefaultUserName) {
		asApplications.get(appId).setDefaultUserName(asDefaultUserName);
	}

	/**
	 * Returns the default password for Analysis Services <br>
	 * The default password will be used only in
	 * <code>BASIC</code> or <code>CUSTOMIZED</code>
	 * authentication mode and only when an password is not 
	 * provided by user (Eg. user input in GUI)
	 * @param appId as-application id
	 * @return the asDefaultUserPassword
	 */
	public String getAsDefaultUserPassword(String appId) {
		return asApplications.get(appId).getDefaultUserPassword();
	}

	/**
	 * Sets the default password for Analysis Services <br>
	 * The default password will be used only in
	 * <code>BASIC</code> or <code>CUSTOMIZED</code>
	 * authentication mode and only when an password is not 
	 * provided by user (Eg. user input in GUI)
	 * @param appId as-application id
	 * @param asDefaultUserPassword the asDefaultUserPassword to set
	 */
	public void setAsDefaultUserPassword(String appId, String asDefaultUserPassword) {
		asApplications.get(appId).setDefaultUserPassword(asDefaultUserPassword);
	}

	/**
	 * Returns the driver used to construct an olap4j connection for Analysis Services
	 * @param appId as-application id
	 * @return the asDriverName
	 */
	public String getAsDriverName(String appId) {
		return asApplications.get(appId).getDriverName();
	}

	/**
	 * Sets the driver used to construct an olap4j connection for Analysis Services
	 * @param appId as-application id
	 * @param asDriverName the asDriverName to set
	 */
	public void setAsDriverName(String appId, String asDriverName) {
		asApplications.get(appId).setDriverName(asDriverName);
	}

	/**
	 * Returns the server where Analysis Services is accessible by HTTP
	 * @param appId as-application id
	 * @return the asServerName
	 */
	public String getAsServerName(String appId) {
		return asApplications.get(appId).getServerName();
	}

	/**
	 * Sets the server where Analysis Services is accessible by HTTP
	 * @param appId as-application id
	 * @param asServerName the asServerName to set
	 */
	public void setAsServerName(String appId, String asServerName) {
		asApplications.get(appId).setServerName(asServerName);
	}

	/**
	 * Returns the IIS web service extension of the server where 
	 * Analysis Services is accessible by HTTP
	 * @param appId as-application id
	 * @return the asWebserviceExtensionName
	 */
	public String getAsWebserviceExtensionName(String appId) {
		return asApplications.get(appId).getWebserviceExtensionName();
	}

	/**
	 * Sets the IIS web service extension of the server where 
	 * Analysis Services is accessible by HTTP
	 * @param appId as-application id
	 * @param asWebserviceExtensionName the asWebserviceExtensionName to set
	 */
	public void setAsWebserviceExtensionName(String appId, String asWebserviceExtensionName) {
		asApplications.get(appId).setWebserviceExtensionName(asWebserviceExtensionName);
	}

	/**
	 * Returns the IIS ISAPI extension of the server where 
	 * Analysis Services is accessible by HTTP
	 * @param appId as-application id
	 * @return the asIsapiExtensionName
	 */
	public String getAsIsapiExtensionName(String appId) {
		return asApplications.get(appId).getIsapiExtensionName();
	}

	/**
	 * Sets the IIS ISAPI extension of the server where 
	 * Analysis Services is accessible by HTTP
	 * @param appId as-application id
	 * @param asIsapiExtensionName the asIsapiExtensionName to set
	 */
	public void setAsIsapiExtensionName(String appId, String asIsapiExtensionName) {
		asApplications.get(appId).setIsapiExtensionName(asIsapiExtensionName);
	}

	/**
	 * Returns the catalog where exists the cubes to visit
	 * @param appId as-application id
	 * @return the asCatalogName
	 */
	public String getAsCatalogName(String appId) {
		return asApplications.get(appId).getCatalogName();
	}

	/**
	 * Sets the catalog where exists the cubes to visit
	 * @param appId as-application id
	 * @param asCatalogName the asCatalogName to set
	 */
	public void setAsCatalogName(String appId, String asCatalogName) {
		asApplications.get(appId).setCatalogName(asCatalogName);
	}

	/**
	 * Returns the initial cube to visit
	 * @param appId as-application id
	 * @return the asCubeName
	 */
	public String getAsCubeName(String appId) {
		return asApplications.get(appId).getCubeName();
	}

	/**
	 * Sets the initial cube to visit
	 * @param appId as-application id
	 * @param asCubeName the asCubeName to set
	 */
	public void setAsCubeName(String appId, String asCubeName) {
		asApplications.get(appId).setCubeName(asCubeName);
	}

	/**
	 * Returns minimum idle connection number of the olap4j connection pool
	 * @param appId as-application id
	 * @return the asPoolMinIdle
	 */
	public int getAsPoolMinIdle(String appId) {
		return asApplications.get(appId).getPoolMinIdle();
	}

	/**
	 * Sets minimum idle connection number of the olap4j connection pool
	 * @param appId as-application id
	 * @param asPoolMinIdle the asPoolMinIdle to set
	 */
	public void setAsPoolMinIdle(String appId, int asPoolMinIdle) {
		asApplications.get(appId).setPoolMinIdle(asPoolMinIdle);
	}

	/**
	 * Returns maximum idle connection number of the olap4j connection pool
	 * @param appId as-application id
	 * @return the asPoolMaxIdle
	 */
	public int getAsPoolMaxIdle(String appId) {
		return asApplications.get(appId).getPoolMaxIdle();
	}

	/**
	 * Sets maximum idle connection number of the olap4j connection pool
	 * @param appId as-application id
	 * @param asPoolMaxIdle the asPoolMaxIdle to set
	 */
	public void setAsPoolMaxIdle(String appId, int asPoolMaxIdle) {
		asApplications.get(appId).setPoolMaxIdle(asPoolMaxIdle);
	}

	/**
	 * Returns maximum active connection number of the olap4j connection pool
	 * @param appId as-application id
	 * @return the asPoolMaxActive
	 */
	public int getAsPoolMaxActive(String appId) {
		return asApplications.get(appId).getPoolMaxActive();
	}

	/**
	 * Sets maximum active connection number of the olap4j connection pool
	 * @param appId as-application id
	 * @param asPoolMaxActive the asPoolMaxActive to set
	 */
	public void setAsPoolMaxActive(String appId, int asPoolMaxActive) {
		asApplications.get(appId).setPoolMaxActive(asPoolMaxActive);
	}

	/**
	 * Returns maximum wait time to obtain a connection from the olap4j connection pool
	 * @param appId as-application id
	 * @return the asPoolMaxWait
	 */
	public int getAsPoolMaxWait(String appId) {
		return asApplications.get(appId).getPoolMaxWait();
	}

	/**
	 * Sets maximum wait time to obtain an connection from the olap4j connection pool
	 * @param appId as-application id
	 * @param asPoolMaxWait the asPoolMaxWait to set
	 */
	public void setAsPoolMaxWait(String appId, int asPoolMaxWait) {
		asApplications.get(appId).setPoolMaxWait(asPoolMaxWait);
	}

	/**
	 * Returns the authentication mode used for Reporting Services
	 * @param appId rs-application id
	 * @return the rsAuthMode
	 */
	public AsRsAuthMode getRsAuthMode(String appId) {
		return rsApplications.get(appId).getAuthMode();
	}

	/**
	 * Sets the authentication mode used for Reporting Services
	 * @param appId rs-application id
	 * @param rsAuthMode the rsAuthMode to set
	 */
	public void setRsAuthMode(String appId, AsRsAuthMode rsAuthMode) {
		rsApplications.get(appId).setAuthMode(rsAuthMode);
	}

	/**
	 * Returns the authentication mode used for Reporting Services <br>
	 * The default username will be used only in
	 * <code>BASIC</code> or <code>CUSTOMIZED</code>
	 * authentication mode and only when an password is not 
	 * provided by user (Eg. user input in GUI)
	 * @param appId rs-application id
	 * @return the rsDefaultUserName
	 */
	public String getRsDefaultUserName(String appId) {
		return rsApplications.get(appId).getDefaultUserName();
	}

	/**
	 * Sets the authentication mode used for Reporting Services <br>
	 * The default username will be used only in
	 * <code>BASIC</code> or <code>CUSTOMIZED</code>
	 * authentication mode and only when an password is not 
	 * provided by user (Eg. user input in GUI)
	 * @param appId rs-application id
	 * @param rsDefaultUserName the rsDefaultUserName to set
	 */
	public void setRsDefaultUserName(String appId, String rsDefaultUserName) {
		rsApplications.get(appId).setDefaultUserName(rsDefaultUserName);
	}

	/**
	 * Returns the authentication mode used for Reporting Services <br>
	 * The default password will be used only in
	 * <code>BASIC</code> or <code>CUSTOMIZED</code>
	 * authentication mode and only when an password is not 
	 * provided by user (Eg. user input in GUI)
	 * @param appId rs-application id
	 * @return the rsDefaultUserPassword
	 */
	public String getRsDefaultUserPassword(String appId) {
		return rsApplications.get(appId).getDefaultUserPassword();
	}

	/**
	 * Sets the authentication mode used for Reporting Services <br>
	 * The default password will be used only in
	 * <code>BASIC</code> or <code>CUSTOMIZED</code>
	 * authentication mode and only when an password is not 
	 * provided by user (Eg. user input in GUI)
	 * @param appId rs-application id
	 * @param rsDefaultUserPassword the rsDefaultUserPassword to set
	 */
	public void setRsDefaultUserPassword(String appId, String rsDefaultUserPassword) {
		rsApplications.get(appId).setDefaultUserPassword(rsDefaultUserPassword);
	}

	/**
	 * Returns the name space URI used in Reporting Services
	 * @param appId rs-application id
	 * @return the rsNameSpaceUri
	 */
	public String getRsNameSpaceUri(String appId) {
		return rsApplications.get(appId).getNameSpaceUri();
	}

	/**
	 * Sets the name space URI used in Reporting Services
	 * @param appId rs-application id
	 * @param rsNameSpaceUri the rsNameSpaceUri to set
	 */
	public void setRsNameSpaceUri(String appId, String rsNameSpaceUri) {
		rsApplications.get(appId).setNameSpaceUri(rsNameSpaceUri);
	}

	/**
	 * Returns the local part used in Reporting Services
	 * @param appId rs-application id
	 * @return the rsLocalPart
	 */
	public String getRsLocalPart(String appId) {
		return rsApplications.get(appId).getLocalPart();
	}

	/**
	 * Sets the local part used in Reporting Services
	 * @param appId rs-application id
	 * @param rsLocalPart the rsLocalPart to set
	 */
	public void setRsLocalPart(String appId, String rsLocalPart) {
		rsApplications.get(appId).setLocalPart(rsLocalPart);
	}

	/**
	 * Returns the WSDL URI used in Reporting Services
	 * @param appId rs-application id
	 * @return the rsWsdlUri
	 */
	public String getRsWsdlUri(String appId) {
		return rsApplications.get(appId).getWsdlUri();
	}

	/**
	 * Sets the WSDL URI used in Reporting Services
	 * @param appId rs-application id
	 * @param rsWsdlUri the rsWsdlUri to set
	 */
	public void setRsWsdlUri(String appId, String rsWsdlUri) {
		rsApplications.get(appId).setWsdlUri(rsWsdlUri);
	}

	/**
	 * Returns the endpoint used in Reporting Services
	 * @param appId rs-application id
	 * @return the rsEndpointUri
	 */
	public String getRsEndpointUri(String appId) {
		return rsApplications.get(appId).getEndpointUri();
	}

	/**
	 * Sets the endpoint used in Reporting Services
	 * @param appId rs-application id
	 * @param rsEndpointUri the rsEndpointUri to set
	 */
	public void setRsEndpointUri(String appId, String rsEndpointUri) {
		rsApplications.get(appId).setEndpointUri(rsEndpointUri);
	}

	/**
	 * Returns minimum idle proxy number of the web service proxy pool
	 * @param appId rs-application id
	 * @return the rsPoolMinIdle
	 */
	public int getRsPoolMinIdle(String appId) {
		return rsApplications.get(appId).getPoolMinIdle();
	}

	/**
	 * Sets minimum idle proxy number of the web service proxy pool
	 * @param appId rs-application id
	 * @param rsPoolMinIdle the rsPoolMinIdle to set
	 */
	public void setRsPoolMinIdle(String appId, int rsPoolMinIdle) {
		rsApplications.get(appId).setPoolMinIdle(rsPoolMinIdle);
	}

	/**
	 * Returns maximum idle proxy number of the web service proxy pool
	 * @param appId rs-application id
	 * @return the rsPoolMaxIdle
	 */
	public int getRsPoolMaxIdle(String appId) {
		return rsApplications.get(appId).getPoolMaxIdle();
	}

	/**
	 * Set maximum idle proxy number of the web service proxy pool
	 * @param appId rs-application id
	 * @param rsPoolMaxIdle the rsPoolMaxIdle to set
	 */
	public void setRsPoolMaxIdle(String appId, int rsPoolMaxIdle) {
		rsApplications.get(appId).setPoolMaxIdle(rsPoolMaxIdle);
	}

	/**
	 * Returns maximum active proxy number of the web service proxy pool
	 * @param appId rs-application id
	 * @return the rsPoolMaxActive
	 */
	public int getRsPoolMaxActive(String appId) {
		return rsApplications.get(appId).getPoolMaxActive();
	}

	/**
	 * Sets maximum active proxy number of the web service proxy pool
	 * @param appId rs-application id
	 * @param rsPoolMaxActive the rsPoolMaxActive to set
	 */
	public void setRsPoolMaxActive(String appId, int rsPoolMaxActive) {
		rsApplications.get(appId).setPoolMaxActive(rsPoolMaxActive);
	}

	/**
	 * Returns maximum wait time to obtain a proxy from the web service proxy pool
	 * @param appId rs-application id
	 * @return the rsPoolMaxWait
	 */
	public int getRsPoolMaxWait(String appId) {
		return rsApplications.get(appId).getPoolMaxWait();
	}

	/**
	 * Sets maximum wait time to obtain a proxy from the web service proxy pool
	 * @param appId rs-application id
	 * @param rsPoolMaxWait the rsPoolMaxWait to set
	 */
	public void setRsPoolMaxWait(String appId, int rsPoolMaxWait) {
		rsApplications.get(appId).setPoolMaxWait(rsPoolMaxWait);
	}

	/**
	 * Returns a list of XML config files where defined all the reports to visit
	 * @param appId rs-application id
	 * @return the rsReportFileList
	 */
//	public List<String> getRsReportFileList(String appId) {
//		return rsApplications.get(appId).getReportFileList();
//	}

	/**
	 * Sets a list of XML config files where defined all the reports to visit
	 * @param appId rs-application id
	 * @param rsReportFileList the rsReportFileList to set
	 */
//	public void setRsReportFileList(String appId, List<String> rsReportFileList) {
//		rsApplications.get(appId).setReportFileList(rsReportFileList);
//	}

	/**
	 * Returns a map which contains all user defined reports
	 * @param appId rs-application id
	 * @return the rsReportList
	 */
//	public Map<String, String> getRsReportList(String appId) {
//		return rsApplications.get(appId).getReportList();
//	}

	/**
	 * Sets a map which contains all user defined reports
	 * @param appId rs-application id
	 * @param rsReportList the rsReportList to set
	 */
//	public void setRsReportList(String appId, Map<String, String> rsReportList) {
//		rsApplications.get(appId).setReportList(rsReportList);
//	}
	
	public void putReport(RsReport report) {
		rsReports.put(report);
	}
	
	public RsReport getReport(String appId, String name) {
		return rsReports.get(appId, name);
	}
	
	public AsRsAuthenticator getRsAuthenticator(String appId) {
		AsRsAuthenticator auth = null;
		AsRsAuthMode mode = this.getRsAuthMode(appId);
		if (mode == AsRsAuthMode.BASIC || mode == AsRsAuthMode.CUSTOMIZED) {
			String username = this.getRsDefaultUserName(appId);
			String password = this.getRsDefaultUserPassword(appId);
			auth = new AsRsAuthenticator(mode, username, password);
		} else {
			auth = new AsRsAuthenticator(mode);
		}
		return auth;
	}
	
	public AsRsAuthenticator getAsAuthenticator(String appId) {
		AsRsAuthenticator auth = null;
		AsRsAuthMode mode = this.getAsAuthMode(appId);
		if (mode == AsRsAuthMode.BASIC || mode == AsRsAuthMode.CUSTOMIZED) {
			String username = this.getAsDefaultUserName(appId);
			String password = this.getAsDefaultUserPassword(appId);
			auth = new AsRsAuthenticator(mode, username, password);
		} else {
			auth = new AsRsAuthenticator(mode);
		}
		return auth;
	}
}